package com.edwin.websitebe.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.edwin.websitebe.dto.GameDTO;
import com.edwin.websitebe.dto.LoginDTO;
import com.edwin.websitebe.model.Game;
import com.edwin.websitebe.model.GameType;
import com.edwin.websitebe.model.Notice;
import com.edwin.websitebe.model.User;
import com.edwin.websitebe.service.*;
import com.edwin.websitebe.util.TokenUtil;
import com.edwin.websitebe.vo.LoginVO;
import com.edwin.websitebe.vo.ResultVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;

@RestController
@RequestMapping("/api")
@Slf4j
public class GameApiController {

    @Autowired
    private GameService gameService;

    @Autowired
    private NoticeService noticeService;

    @Autowired
    private GameTypeService gameTypeService;

    @Autowired
    private UserService userService;

    @Autowired
    private OrderService orderService;


    @PostMapping("/login")
    public ResultVO login(@Validated @RequestBody LoginDTO dto) {
        User user = userService.getByUsername(dto.getUsername());
        if (Objects.isNull(user)) {
            return new ResultVO().fail("1", "用户不存在");
        }
//        boolean match = DigestUtil.sha256Hex(dto.getPassword()).equals(user.getPassword());
        boolean match = dto.getPassword().equals(user.getPassword());
        if (match) {
            LoginVO loginVO = new LoginVO();
            loginVO.setToken(TokenUtil.createToken(user.getId()));
            return new ResultVO().success(loginVO);
        } else {
            return new ResultVO().fail("1", "密码错误");
        }

    }

    @GetMapping("/listGameType")
    public ResultVO listGameType() {
        List<GameType> list = gameTypeService.list();
        return new ResultVO().success(list);
    }

    @GetMapping("/list")
    public ResultVO<List<Game>> list(
            @RequestParam(required = false) String gameName,
            @RequestParam(required = false) Long typeId,
            @RequestParam(required = false) Long page,
            @RequestParam(required = false) Long pageSize
    ) {
        if (Objects.isNull(page)) {
            page = 1L;
        }
        if (Objects.isNull(pageSize)) {
            pageSize = 10L;
        }
        IPage<Game> gameList = gameService.page(gameName, typeId, page, pageSize);
        List<Game> records = gameList.getRecords();
        records.forEach(game -> game.setGameSize(game.getGameSize().setScale(2, RoundingMode.HALF_UP)));
        return new ResultVO<List<Game>>().success(records);
    }

    @GetMapping("/getGameById")
    public ResultVO getGameById(@RequestParam Long gameId) {
        Game game = gameService.getById(gameId);
        return new ResultVO().success(game);
    }

    @GetMapping("/listGameTypeByGameId")
    public ResultVO listGameTypeByGameId(@RequestParam Long gameId) {
        List<GameType> list = gameTypeService.listByGameId(gameId);
        return new ResultVO().success(list);
    }

    @PostMapping("/calc")
    public ResultVO<BigDecimal> calc(@RequestBody GameDTO dto) {
        List<Long> gameIdList = dto.getGameIdList();
        if (gameIdList == null || gameIdList.size() == 0) {
            return new ResultVO<BigDecimal>().success(BigDecimal.ZERO);
        }
        LambdaQueryWrapper<Game> wrapper = new QueryWrapper<Game>().lambda()
                .in(Game::getId, dto.getGameIdList());
        List<Game> gameList = gameService.list(wrapper);
        BigDecimal size = gameList.stream()
                .map(Game::getGameSize)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        return new ResultVO<BigDecimal>().success(size);

    }

    @PostMapping("/parseSelectedCode")
    public ResultVO<String> parseSelectedCode(@RequestBody GameDTO dto) {
        List<Long> gameIdList = dto.getGameIdList();
        if (gameIdList == null || gameIdList.size() == 0) {
            return new ResultVO<String>().success("-");
        }
        LambdaQueryWrapper<Game> wrapper = new QueryWrapper<Game>().lambda()
                .in(Game::getId, dto.getGameIdList());
        List<Game> gameList = gameService.list(wrapper);
        gameList.sort(Comparator.comparing(Game::getGameCode));
        String result = "";
        if (gameList.size() <= 2) {
            for (Game game : gameList) {
                result += game.getGameCode() + ",";
            }
            result = result.substring(0, result.length() - 1);
        } else {
            result = gameList.get(0).getGameCode() + "," + gameList.get(1).getGameCode() + "...";
        }
        return new ResultVO<String>().success(result);

    }

    @PostMapping("/listSelected")
    public ResultVO<List<Game>> listSelected(@RequestBody GameDTO dto) {
        List<Long> gameIdList = dto.getGameIdList();
        if (gameIdList == null || gameIdList.size() == 0) {
            return new ResultVO<List<Game>>().success(Collections.emptyList());
        }
        LambdaQueryWrapper<Game> wrapper = new QueryWrapper<Game>().lambda()
                .in(Game::getId, dto.getGameIdList());
        List<Game> gameList = gameService.list(wrapper);
        gameList.sort(Comparator.comparing(Game::getGameCode));
        return new ResultVO<List<Game>>().success(gameList);
    }

    @GetMapping("/listNotice")
    public ResultVO<List<Notice>> listNotice() {
        LambdaQueryWrapper<Notice> wrapper = new QueryWrapper<Notice>().lambda()
                .orderByAsc(Notice::getNoticeCode);
        List<Notice> list = noticeService.list(wrapper);
        return new ResultVO<List<Notice>>().success(list);
    }

    @GetMapping("getGameByCode")
    public ResultVO<Game> getGameByCode(@RequestParam String code) {
        LambdaQueryWrapper<Game> wrapper = new QueryWrapper<Game>().lambda()
                .eq(Game::getGameCode, code.trim());
        List<Game> gameList = gameService.list(wrapper);
        Game result = null;
        if (CollectionUtil.isNotEmpty(gameList)) {
            result = gameList.get(0);
        }
        return new ResultVO<Game>().success(result);
    }

    @GetMapping("/listGameByCode")
    public ResultVO listGameByCode(@RequestParam String code) {

        List<Game> games = orderService.listGameByOrderCode(code);


        return new ResultVO().success(games);
    }

    @PostMapping("/makeOrder")
    public ResultVO makeOrder() {



        String code = IdUtil.getSnowflakeNextIdStr();

        return new ResultVO().success(code);
    }

}
